#include <iostream>
#include <string>
#include <memory>
#include <algorithm>
#include <cctype>
#include "TcpServer.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Translate.hpp"
#include "Daemon.hpp"

using namespace std;

Translate trans;

void Usage(const string& proc)
{
    cout << proc << " localport\n" << endl;
}

// 未来我们不知道我们的服务器在任意一个时刻是否是健康的
// 所以我们可以让客户端定期的向服务器发送最小请求，若服务器有回应，则说明服务正常
// 这种机制我们称之为心跳机制 
// ping服务，客户端发如何消息，服务端回复pong，表示服务器健康
void Ping(int sockfd,InetAddr& inetaddr)
{
    lg.LogMessage(Info,"%s select ping\n",inetaddr.PrintDebug().c_str());

    char buffer[1024];
    int n = read(sockfd,buffer,sizeof(buffer) - 1);
    if(n > 0)
    {
        string response = "Pong";
        write(sockfd,response.c_str(),response.size());
    }
    else if(n == 0)
    {
        lg.LogMessage(Warning,"client quit\n");
    }
    else
    {
        lg.LogMessage(Fatal,"read socket error , errno : %d , error string : %s\n",errno,strerror(errno));
    }
}

// 提供翻译服务，客户端发送一个单词，服务端返回单词的翻译
void Translate(int sockfd,InetAddr& inetaddr)
{
    lg.LogMessage(Info,"%s select translate\n",inetaddr.PrintDebug().c_str());
    
    char buffer[1024];
    int n = read(sockfd,buffer,sizeof(buffer) - 1);
    if(n > 0)
    {
        buffer[n] = 0;
        string word = buffer;
        string response = trans.Execute(word);
        write(sockfd,response.c_str(),response.size());
    }
    else if(n == 0)
    {
        lg.LogMessage(Warning,"client quit\n");
    }
    else
    {
        lg.LogMessage(Fatal,"read socket error , errno : %d , error string : %s\n",errno,strerror(errno));
    }
}

// 提供转大写服务，服务端将客户端发送的信息，全部转换为大写再发送给客户端
void TransForm(int sockfd,InetAddr& inetaddr)
{
    lg.LogMessage(Info,"%s select transform\n",inetaddr.PrintDebug().c_str());

    char buffer[1024];
    int n = read(sockfd,buffer,sizeof(buffer) - 1);
    if(n > 0)
    {
        buffer[n] = 0;
        string messages = buffer;
        string response(messages.size(),' ');
        std::transform(messages.begin(),messages.end(),response.begin(),[](unsigned char c){return toupper(c);});
        write(sockfd,response.c_str(),response.size());
    }
    else if(n == 0)
    {
        lg.LogMessage(Warning,"client quit\n");
    }
    else
    {
        lg.LogMessage(Fatal,"read socket error , errno : %d , error string : %s\n",errno,strerror(errno));
    }
}

int main(int argc , char* argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }

    uint16_t ServerPort = stoi(argv[1]);

    Daemon(true,true);
    lg.SwitchStyle(OneFile);

    unique_ptr<TcpServer> uq = make_unique<TcpServer>(ServerPort);

    uq->RegisterFunc("ping",Ping);
    uq->RegisterFunc("translate",Translate);
    uq->RegisterFunc("transform",TransForm);

    uq->Init();
    uq->Start();

    return 0;
}